/*
 * @Author: wuqingchun
 * @Date: 2024-03-29 10:52:21
 * @Description: 内存分配器实现
 * @LastEditors: wuqingchun
 * @LastEditTime: 2024-03-30 15:21:42
 */
#include <stdint.h>

#include "mem_allocator.h"

// 数字 n 按 大小 a 进行对齐
#ifndef ALIGN
//#define ALIGN(n,m) (((n + m - 1) / m) * m)
#define ALIGN(n, a) (((n) + (a) - 1) & ~((a) - 1))
#endif //ALIGN

MemAllocator::MemAllocator(/* args */)
{
    for (uint32_t uiIndex = 0; uiIndex < MEM_SIZE_LEVEL; uiIndex++)
    {
        m_mapIndex[8 << uiIndex] = uiIndex;
    }
}

MemAllocator::~MemAllocator()
{
}

void *MemAllocator::Alloc(size_t ulSize)
{
    void* pRet = nullptr;
    
    ulSize = ALIGN(ulSize, 8);
    if (ulSize == 0)
    {
        return pRet;
    }
    
    // 查找指定大小的 free list
    for (uint32_t uiIndex = __Size2Index(ulSize); uiIndex < m_arrFreeList.size(); uiIndex++)
    {
        //printf("uiIndex: %u, %lu\n", uiIndex, ulSize);
        auto& flist = m_arrFreeList[uiIndex];
        if (flist.empty())
        {
            // 如果小的空闲链表中没有内存，需要从大的里面分配
            continue;
        }

        MemNode& refBlock = flist.front();
        //printf("freelist: %u, %lu, %lu\n", uiIndex, flist.size(), refBlock.ulSize);
        
        //printf("MemNode: %u, %lu, %p, %lu\n", uiIndex, flist.size(), refBlock.pPtr, refBlock.ulSize);
        pRet = __AllocMemNode(refBlock, ulSize);
        if (pRet != nullptr)
        {
            flist.pop_front();
            return pRet;
        }
    }

    // 从系统申请内存
    void* pPtr = malloc(MEM_ALLOC_MAX_SIZE);
    if (pPtr == nullptr)
    {
        return nullptr;
    }
    
    m_vecMemPool.push_back({pPtr, MEM_ALLOC_MAX_SIZE, 0});
    MemNode stNode {pPtr, MEM_ALLOC_MAX_SIZE, (uint32_t)m_vecMemPool.size() - 1};

    //printf("=========\n");
    return __AllocMemNode(stNode, ulSize);
}

void MemAllocator::Free(void *pPtr)
{

}

void * MemAllocator::__AllocMemNode(MemNode& refNode, size_t ulAllocSize)
{
    //printf("__AllocMemNode: %lu, %p, %lu, %u\n", ulAllocSize, refNode.pPtr, refNode.ulSize, refNode.uiBlockID);
    if (refNode.ulSize == ulAllocSize)
    {
        //printf("__AllocMemNode Successfully: %lu, %p, %lu, %u\n", ulAllocSize, refNode.pPtr, refNode.ulSize, refNode.uiBlockID);
        m_mapUsedMem.emplace(refNode.pPtr, refNode);

        m_vecMemPool[refNode.uiBlockID].uiRefCount++;

        return refNode.pPtr;
    }

    // 一分为二

    // 插入对应的空闲链
    size_t ulTmpSize = (refNode.ulSize >> 1);
    uint32_t uiIndex = __Size2Index(ulTmpSize);
    if (uiIndex == (uint32_t)-1)
    {
        printf("Bad length, %lu\n", ulTmpSize);
        return nullptr;
    }

    //printf("AddMemNode: %u, %lu, %p, %lu\n", uiIndex, ulTmpSize, refNode.pPtr, refNode.ulSize);
    m_arrFreeList[uiIndex].push_back({refNode.pPtr, ulTmpSize, refNode.uiBlockID});

    refNode.pPtr = (char*)refNode.pPtr + ulTmpSize;
    refNode.ulSize = ulTmpSize;

    return __AllocMemNode(refNode, ulAllocSize);
}

uint32_t MemAllocator::__Size2Index(size_t ulSize)
{
    // 计算
    auto it = m_mapIndex.find(ulSize);
    if (it == m_mapIndex.end())
    {
        return (uint32_t)-1;
    }

    return it->second;
}


void MemAllocator::ShowMemInfo()
{
    printf("MemBockCount: %lu\n", m_vecMemPool.size());

    uint32_t uiIndex = 0;

    for (auto& item : m_vecMemPool)
    {
        printf("[%u]: %p, %lu, %u\n", uiIndex++, item.pPtr, item.ulSize, item.uiRefCount);
    }

    size_t ulSize = 8;
    uint32_t uiCount = 1;
    for (auto& list : m_arrFreeList)
    {
        printf("list [%lu]: %lu\n", ulSize, list.size());
        for (auto& node : list)
        {
            printf("%p, %u, %lu\n", node.pPtr, node.uiBlockID, node.ulSize);
        }
        printf("\n");

        ulSize <<= 1;
    }

    printf("\n");
}